#include "SEGGER_RTT_Port.h"
#include "SEGGER_RTT.h"


#include "stm32f1xx_hal.h"
#include "main_user.h"

char JS_RTT_UpBuffer[4096];    // J-Scope RTT Buffer
int  JS_RTT_Channel = 1;       // J-Scope RTT Channel


static inline tb_tick_t tb_read_ticks(void)
{
    return (tb_tick_t)DWT->CYCCNT;
    //return (tb_tick_t)tb_tim->CNT;
}


/* -------------------- converter（可替换） --------------------
   把 delta_ticks 转成整数微秒 us_inc 和余数 rem_inc（两者以输出参数返回）
   base_hz     - tick 频率(Hz)，例如 DWT 为 SystemCoreClock，TIM 为 timer_tick_hz
*/
#define s_tb_base_hz  (SystemCoreClock)
//#define s_tb_base_hz  (timer_tick_hz)
static inline void tb_convert_delta_parts(uint32_t delta_ticks, uint64_t *us_inc, uint64_t *rem_inc)
{
    uint64_t tmp = (uint64_t)delta_ticks * 1000000ULL;
    uint64_t base = (uint64_t)s_tb_base_hz;
    *us_inc = tmp / base;
    *rem_inc = tmp % base;
}


/* Internal state */
static volatile uint32_t  s_last_cycles = 0;
static volatile uint64_t  s_us_acc = 0;   /* accumulated microseconds (monotonic) */
static volatile uint64_t  s_rem = 0;      /* accumulated remainder in cycles */


void SEGGER_RTT_TimeStamp_reset(void)
{
       /* 将内部累加归零，并把 last_cycles 设为当前 CYCCNT 以避免下一次产生大 delta */
    __disable_irq();
    s_us_acc = 0;
    s_rem = 0;
    s_last_cycles = tb_read_ticks();
     __enable_irq();
}

/* 返回 32-bit 微秒计数（单调，受 reset 影响） */
uint32_t SEGGER_RTT_TimeStamp_get(void)
{
    uint32_t cur = tb_read_ticks();

    /* 进入临界区更新状态（短期禁中断） */
    __disable_irq();

    uint32_t delta_cycles = cur - s_last_cycles; /* 无符号差自然处理 wrap */
    s_last_cycles = cur;

 
    uint64_t us_inc = 0;
    uint64_t rem_inc = 0;
    /* cycles -> microseconds (分离整数部分与余数以保精度) */
    tb_convert_delta_parts(delta_cycles, &us_inc, &rem_inc);

    s_us_acc += us_inc;
    s_rem += rem_inc;

    if (s_rem >= (uint64_t)s_tb_base_hz) {
        uint64_t carry = s_rem / (uint64_t)s_tb_base_hz;
        s_us_acc += carry;
        s_rem = s_rem % (uint64_t)s_tb_base_hz;
    }


    __enable_irq();

    /* 返回低 32 位（unsigned int），表示微秒时间戳模 2^32 */
    return (unsigned int)(s_us_acc & 0xFFFFFFFFU);
}

void SEGGER_RTT_Port_Init(void) {

    /* Initialize RTT for communication with J-Scope */
    SEGGER_RTT_ConfigUpBuffer(JS_RTT_Channel, "JScope_T4I4I4I4", &JS_RTT_UpBuffer[0], sizeof(JS_RTT_UpBuffer), SEGGER_RTT_MODE_NO_BLOCK_SKIP);
}

extern ADCSamp  ADCSampPare;
void SEGGER_RTT_Port_Write(void) {
    /* Nothing to do */
    //
    // RTT block structure
    //
    #pragma pack(push, 1)
    struct {
        unsigned int Timestamp;
        signed int Variable1;
        signed int Variable2;
        signed int Variable3;
    } acValBuffer;
    #pragma pack(pop)

    acValBuffer.Timestamp = SEGGER_RTT_TimeStamp_get();
    acValBuffer.Variable1 = ADCSampPare.PhaseU_CurrFitter;
    acValBuffer.Variable2 = ADCSampPare.PhaseV_CurrFitter;
    
    SEGGER_RTT_Write(JS_RTT_Channel, &acValBuffer, sizeof(acValBuffer));
}

